package com.gitee.wsl.ext.collection


/**
 * @param selector is a function using which the value by which we reorder is going to be selected, must be the same
 * value that is specified in the [order]
 * @param order a list of objects that represents the order which should be used to sort the original list
 * @returns A copy of this list ordered according to the order
 */
inline fun <T, R> Iterable<T>.reorderBy(order: List<R>, crossinline selector: (T) -> R): List<T> {
    // associate the values with indexes and create a map
    val orderMap = order.withIndex().associate { it.value to it.index }
    // sort the habits sorted using the comparator that places values not present in a map last
    // and uses the order of the items in the map as its basis for sorting.
    return sortedWith(compareBy(nullsLast()) { orderMap[selector(it)] }).toMutableList()
}

/** Invokes the key getter strictly one time for each item (builds list of pairs (item, key), then sorts). */
fun <T, K: Comparable<K>> Collection<T>.sortedByCopy(keyGetter: (T) -> K): List<T> {
    val pairs = map { Pair(it, keyGetter(it)) }.sortedBy { it.second }
    return pairs.map { it.first }
}